home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / quartz / quartz10.lha / src / presto / process.h < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  6.7 KB  |  248 lines

  1. //
  2. //
  3. //    Processes work as hungry puppies, banging on the scheduler
  4. //    until a ready job is available or until someone bangs on the
  5. //    process asking it to do something "out of band" (like pausing
  6. //    or dying).
  7. //
  8. // Modification History:
  9. //
  10. //   05-Dec-89  John Faust
  11. //   Remove stack free list.  Allocate stacks of fixed size when thread
  12. //   is allocated.  Stack remains associated with owning thread.  More
  13. //   efficient (removes search of stack freelist for stack of proper size,
  14. //   allocation of stack if one of proper size not found, and eliminates
  15. //   need to balance local stack freelists).
  16. //
  17. //   08-Nov-1989  John Faust
  18. //   Implement per-processor free lists of thread templates.
  19. //
  20.  
  21. extern Process *sysproc;
  22.  
  23. class Invocation;
  24.  
  25. //
  26. // Maximum size of global thread freelist, threshhold of local list,
  27. // and number of threads to preallocate for local freelists.
  28. // Note that currently, thread size is 132 bytes.
  29. //
  30. // Using these values, the Create1M benchmark never has to allocate any threads
  31. // once the processes have been initialized.
  32. //
  33. #define GBL_THREAD_FREELIST_MAX    128
  34. #define LCL_THREAD_FREELIST_THRESH   8
  35. #define NUM_PREALLOC_THREADS         4
  36.  
  37.  
  38. class Process    : public Object     {
  39. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  40.     int    p_interruptible;
  41. #endif
  42. #ifdef vax
  43.     // WARNING: The offset of p_interruptible is known to swtch().
  44.     int    p_interruptible;
  45. #endif vax
  46.     char    *p_name;            // my name
  47.     int    p_id;                // my id
  48.     // WARNING: The offset of p_pid is known in hc_slock_asm.h
  49.     int    p_pid;                // system pid
  50.     int    p_ppid;                // system ppid
  51.         //
  52.         // Get and free threads from global shared thread freelist.
  53.         // Processes go to the list only when their local freelist becomes
  54.         // empty or when it gets to full.
  55.         //
  56.         void    get_gbl_threads ();
  57.         void    free_gbl_threads ();
  58.  
  59. protected:
  60.     int    p_state;            // whats up
  61.     int     p_flags;            // long term process stuff
  62.     int    p_request;            // stop spinning on this
  63.     Thread  *p_schedthread;            // where to swtch back to 
  64.     Thread    *p_thread;            // currently running thread
  65.         ThreadQUnlocked*    p_thread_freelist;  // per-processor thd freelist
  66. #define NEWPROCESS
  67.     virtual void    p_fork();               // take care of the fork
  68.     virtual void    p_wait();            // where we spin
  69.     virtual void    p_pause();            // internal ::pause
  70.     virtual void    p_runchild(int *spinflag);    // copy stack and go
  71. public:
  72.     Process(int ptag, int id);
  73.     Process();
  74.     Process(char* name, int id, int delayedfork = 0); // fork in ctor
  75.     virtual ~Process();
  76.     // virtual newprocess function.  After creation of the first thisproc,
  77.     // raw process constructor is not used.  thisproc->newprocess() is
  78.     // used instead.  User can assign his own derivation of Process to
  79.     // thisproc in Main::init().
  80.     virtual Process* newprocess(char* name,int id);    
  81.     virtual int    request(int req);
  82.     virtual void    park();            // os pause
  83.     virtual void    drive();        // resume
  84.     virtual int    invoke();
  85.  
  86.         //
  87.         // Get and free threads from per-processor freelist.
  88.         //
  89.         inline Thread* get_thread (int* init_reqd);
  90.         inline void    free_thread (Thread* t);
  91.  
  92.     int    state()
  93.         { return p_state; }
  94.     void     setstate(int st)
  95.         { p_state = st; }
  96.     int     flags()
  97.         { return p_flags; }
  98.     inline int isroot();
  99.     int    id()                // scheduler id
  100.         {return p_id; }    
  101.     int    pid()            // unix id
  102.         { return p_pid; }
  103.     int     ppid()            // unix parent id
  104.         { return p_ppid; }
  105.     char *    name()
  106.         { return p_name; }
  107.     Thread    *schedthread()
  108.         { return p_schedthread; }
  109.     Thread    *runningthread()
  110.         { return p_thread; }
  111. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  112.     int    interruptible()
  113.         { return p_interruptible; }
  114.     inline int disable_interrupts();
  115.     void enable_interrupts()
  116.         { p_interruptible = 1; }
  117. #endif sun
  118. #ifdef vax
  119.     int    interruptible()
  120.         { return p_interruptible; }
  121.     inline int disable_interrupts();
  122.     void enable_interrupts()
  123.         { p_interruptible = 1; }
  124. #endif vax
  125.     virtual void print(ostream& = cout);
  126.     virtual void    error(char *s);
  127. };
  128.  
  129.     
  130. #define R_NULL        0x00    /* nothing is happening */
  131. #define R_WAKEUP    0x01    /* wakeup wherever you are */
  132. #define R_PARK        0x02    /* put yourself to sleep in the OS */
  133. #define R_DIE        0x04    /* the nice way to kill a process */
  134. #define R_RETURN    0x08    /* relinquish control */
  135. /*
  136.  * We don't need R_DIE and R_RETURN since the process wait routine
  137.  * only understands how to R_RETURN from its scheduling loop.  Where
  138.  * it returns to is completely determined by how it was invoked.
  139.  * If it was invoked from runchild, then we will return to there
  140.  * and get nuked with a (delete this).  If we were called via runrun
  141.  * from the Main constructor, then we will return to single threaded
  142.  * control.
  143.  */
  144.  
  145. #define S_RUN        0x01    /* running */
  146. #define S_WAIT        0x02    /* unused.  waiting to be used in spinloop */
  147. #define S_SLEEP        0x04    /* sleeping on an event */
  148. #define S_OSPAUSE    0x08    /* WAITing or SLEEPing via OS pause */
  149. #define S_FREE        (S_WAIT|S_OSPAUSE)
  150. #define S_ZOMBIE    0x10
  151. #define S_EXITING    0x20
  152. #define S_DELAYEDFORK    0x40    /* constructed, but not yet forked */
  153. #define S_FORKING    0x80    /* as we speak... */
  154. #define S_ERROR        0x100
  155. #define S_REAPED    0x200    /* already cleaned up */
  156. #define S_REAPING    0x400    /* parent process cleaning up */
  157.  
  158.  
  159. //
  160. // special proc tags for flags field
  161. //
  162. #define P_ROOT        0x01
  163.  
  164. inline int Process::isroot()
  165. {
  166.     return (p_flags&P_ROOT);
  167. }
  168.  
  169. //
  170. //  Get a thread from the process freelist.  This is an unshared, unprotected
  171. //  queue, so access to it should be very fast.
  172. //
  173. inline Thread*
  174. Process::get_thread (int* init_reqd)
  175. {
  176.     register Thread* t;
  177.  
  178.     //
  179.     //  If this process' local freelist is exhausted, then try to grab some
  180.     //  more threads from the global queue.
  181.     //
  182.     if (p_thread_freelist->length() == 0)
  183.         get_gbl_threads ();
  184.  
  185.     //
  186.     // Check local freelist for reuseable thread.  If none, allocate
  187.     // a new one.
  188.     //
  189.     t = p_thread_freelist->get ();
  190.     if (t)
  191.     {
  192.         *init_reqd = 0;
  193. //      cout << "got thread from freelist\n";
  194.         return t;
  195.     }
  196.     else
  197.     {
  198.         *init_reqd = 1;
  199. //      cout << "had to alloc thread\n";
  200.         return (t = (Thread*) new char [sizeof (Thread)]);
  201.     }
  202. }
  203.  
  204.  
  205. //
  206. //  Return a thread to the local freelist for this process.
  207. //
  208. inline void
  209. Process::free_thread (Thread* t)
  210. {
  211.     p_thread_freelist->append (t);
  212.  
  213.     //
  214.     //  If the local freelist is over threshhold, move half it's threads
  215.     //  to the global freelist.
  216.     //
  217.     if (p_thread_freelist->length() > LCL_THREAD_FREELIST_THRESH)
  218.     {
  219.         free_gbl_threads ();
  220.     }
  221. }
  222.  
  223.  
  224. #if (sun && THREAD_HAS_INTERRUPTIBLE_FIELD)
  225. inline int Process::disable_interrupts()
  226. {
  227.     if (p_interruptible)    {
  228.         p_interruptible = 0;
  229.         return 1;
  230.  
  231.     } else
  232.         return 0;
  233. }
  234. #endif sun
  235. #ifdef vax
  236. inline int Process::disable_interrupts()
  237. {
  238.     if (p_interruptible)    {
  239.         p_interruptible = 0;
  240.         return 1;
  241.  
  242.     } else
  243.         return 0;
  244. }
  245. #endif vax
  246.  
  247. extern private_t Process    *thisproc;    // private to each proc
  248.